package com.fuze.common;

import cn.hutool.http.HttpStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * @author sepc_
 * @date 3/16/2021 14:31
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 自定义异常处理
     *
     * @param e 自定义异常
     * @return 统一返回
     */
    @ExceptionHandler(CustomException.class)
    public Result customExceptionHandler(CustomException e) {
        StackTraceElement traceElement = e.getStackTrace()[0];
        log.error("{} 类的 {} 方法下的 第 {} 行抛出了异常",
                traceElement.getClassName(), traceElement.getMethodName(), traceElement.getLineNumber());
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(e.getCode(), e.getMessage());
    }

    /**
     * 意外的空指针处理
     *
     * @param e 空指针异常
     * @return 统一返回
     */
    @ExceptionHandler(NullPointerException.class)
    public Result npeHandler(NullPointerException e) {
        StackTraceElement stackTraceElement = e.getStackTrace()[0];
        log.error(" {} 类的 {} 方法 的第 {} 行抛出了空指针异常！", stackTraceElement.getClassName(),
                stackTraceElement.getMethodName(), stackTraceElement.getLineNumber());
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, "服务器空指针异常");
    }

    /**
     * 当系统出现MethodArgumentNotValidException这个异常时，会调用下面的方法
     *
     * @param e 异常
     * @return 统一返回结果
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result jsonErrorHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<ObjectError> errorList = bindingResult.getAllErrors();
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, errorList.get(0).getDefaultMessage());

    }

    /**
     * 参数异常处理
     *
     * @param e 参数异常
     * @return 统一返回结果
     */
    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException e) {
        BindingResult result = e.getBindingResult();
        List<ObjectError> errorList = result.getAllErrors();
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, errorList.get(0).getDefaultMessage());
    }

    /**
     * 数据库交互异常 处理
     *
     * @param e 数据库交互异常
     * @return 统一返回
     */
    @ExceptionHandler(SQLException.class)
    public Result sqlExceptionHandler(SQLException e) {
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, "数据库交互异常");
    }

    /**
     * 请求方式错误异常处理
     *
     * @param e 请求方式错误
     * @return 统一返回
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_BAD_METHOD, e.getMessage());
    }

    /**
     * 数组下标越界异常处理
     *
     * @param e 数组下标越界
     * @return 统一返回
     */
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Result indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException e) {
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, "数组下标越界");
    }

    /**
     * 未知的异常处理
     *
     * @param e 后端未知的异常处理
     * @return 统一返回
     */
    @ExceptionHandler(Exception.class)
    public Result exceptionHandler(Exception e) {
        StackTraceElement stackTraceElement = e.getStackTrace()[0];
        log.error(" {} 类的 {} 方法 的第 {} 行抛出了未知的异常！", stackTraceElement.getClassName(),
                stackTraceElement.getMethodName(), stackTraceElement.getLineNumber());
        log.error("这个异常是意外出现的！");
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, "业务其他异常");
    }

    /**
     * HttpMediaTypeNotSupportedException 异常处理
     *
     * @param e 异常
     * @return 统一返回
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException e) {
        log.error("error message : {}", e.getMessage(), e);
        return Result.err(HttpStatus.HTTP_INTERNAL_ERROR, e.getMessage());
    }


}
